10. Load Existing Pet in EditorActivity
Load Existing Pet
Question:
Alright, now we have the URI for our pet in our editor Activity. In this case, we should also load up the pet data from the content provider. We can do this using a CursorLoader.
The difference from when we last used a CursorLoader is that instead of taking the cursor and putting it into a CursorAdapter, we’ll take all of the items from the cursor and use them to populate the EditTextFields.
We will use almost the same steps as before, except that when we make the loader, the uri will be for one pet, and not all of the pets.
Then when we get the Cursor back in onLoadFinished, instead of using a cursor adapter, we’ll update all of the inputs, which basically means the editTexts and gender spinner with the values from the pet.
Finally in our onLoaderReset method, we should clear out the input fields.
Take some time to do that now.
Your Steps:
- Implement the loader callbacks interface
- Initialize the loader
- Write the code for the loader callback method onCreateLoader; make sure it is using a URI for one pet.
- Write the code for the loader callback method onLoadFinished, and update the inputs with the data for the pet.
- Write the code for the loader callback method onLoaderReset, and clear the input fields.
Start Quiz:
Solution:
Start by implementing the loader callbacks and using the Ctrl + I hotkey to get all of the loader callback methods:
public class EditorActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {
Next, initialize the loader, using this code:
getLoaderManager().initLoader(EXISTING_PET_LOADER, null, this);
In onCreateLoader(), I’ll make a new CursorLoader, passing in the uri and the projection. I need the uri from onCreate() so I’ll need to put it in an instance variable called mCurrentPetUri
:
/** Content URI for the existing pet (null if it's a new pet) */
private Uri mCurrentPetUri;
...
@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
// Since the editor shows all pet attributes, define a projection that contains
// all columns from the pet table
String[] projection = {
PetEntry._ID,
PetEntry.COLUMN_PET_NAME,
PetEntry.COLUMN_PET_BREED,
PetEntry.COLUMN_PET_GENDER,
PetEntry.COLUMN_PET_WEIGHT };
// This loader will execute the ContentProvider's query method on a background thread
return new CursorLoader(this, // Parent activity context
mCurrentPetUri, // Query the content URI for the current pet
projection, // Columns to include in the resulting Cursor
null, // No selection clause
null, // No selection arguments
null); // Default sort order
}
When the data from the pet is loaded into a cursor, onLoadFinished() is called. Here, I’ll first most the cursor to it’s first item position. Even though it only has one item, it starts at position -1.
// Proceed with moving to the first row of the cursor and reading data from it
// (This should be the only row in the cursor)
if (cursor.moveToFirst()) {
Then I’ll get the data out of the cursor by getting the index of each data item, and then using the indicees and the get methods to grab the actual integers and strings.
if (cursor.moveToFirst()) {
// Find the columns of pet attributes that we're interested in
int nameColumnIndex = cursor.getColumnIndex(PetEntry.COLUMN_PET_NAME);
int breedColumnIndex = cursor.getColumnIndex(PetEntry.COLUMN_PET_BREED);
int genderColumnIndex = cursor.getColumnIndex(PetEntry.COLUMN_PET_GENDER);
int weightColumnIndex = cursor.getColumnIndex(PetEntry.COLUMN_PET_WEIGHT);
// Extract out the value from the Cursor for the given column index
String name = cursor.getString(nameColumnIndex);
String breed = cursor.getString(breedColumnIndex);
int gender = cursor.getInt(genderColumnIndex);
int weight = cursor.getInt(weightColumnIndex);
For each of the textViews I’ll set the proper text.
// Update the views on the screen with the values from the database
mNameEditText.setText(name);
mBreedEditText.setText(breed);
mWeightEditText.setText(Integer.toString(weight));
For the spinner, I’ll use a switch statement to set its state correctly using the setSelection method.
// Gender is a dropdown spinner, so map the constant value from the database
// into one of the dropdown options (0 is Unknown, 1 is Male, 2 is Female).
// Then call setSelection() so that option is displayed on screen as the current selection.
switch (gender) {
case PetEntry.GENDER_MALE:
mGenderSpinner.setSelection(1);
break;
case PetEntry.GENDER_FEMALE:
mGenderSpinner.setSelection(2);
break;
default:
mGenderSpinner.setSelection(0);
break;
}
INSTRUCTOR NOTE:
Hint #1: When you receive a Cursor result from the loader, remember to move the cursor to the 0th position, before you start extracting out column values from it.
Hint #2: You can use the Spinner’s setSelection() method to set the dropdown spinner to display the correct gender.